'use strict';
import React, { useState, useEffect, useRef } from 'react';
import { Table, Button, Drawer, Form, Input, Select, Divider } from 'antd';
import {
  initListenerType, initListenerForm, listenerTypeObject, fieldTypeObject,
  taskEventType, eventType, columns, listenerFieldFormColumns
} from "./utilSelf";
import { createListenerObject, updateElementExtensions, } from "../../utils";
import {
  PlusOutlined,
  AppstoreFilled
} from '@ant-design/icons';
import Gmodal from '@/component/modal'
import { layout } from '../conf'
import styles from './index.less';

/*
* 组件注释
* create by wuqiong
* creation time 2022/04/24
* 执行监听器
* */
const _layout = {
  labelCol: {
    span: 5,
  },
  wrapperCol: {
    span: 19,
  },
}
const { Option } = Select;
const btn_style = { width: '49%', height: "28px", lineHeight: "28px", fontSize: '12px' }
const Index = (props) => {
  const { id, type, prefix, width, componentType } = props;

  const [eventTypes] = useState(() => componentType === "task" ? taskEventType : eventType);// 监听器列表
  const [elementListenersList, setElementListenersList] = useState([]);// 监听器列表
  const [listenerForm, setListenerForm] = useState({});// 监听器详情表单
  const [listenerFormModelVisible, setListenerFormModelVisible] = useState(false); // 监听器 编辑 侧边栏显示状态
  const [fieldsListOfListener, setFieldsListOfListener] = useState([]);
  const [listenerFieldForm, setListenerFieldForm] = useState({});// 监听器 注入字段 详情表单
  const [listenerFieldFormModelVisible, setListenerFieldFormModelVisible] = useState(false);// 监听器 注入字段表单弹窗 显示状态
  const [editingListenerIndex, setEditingListenerIndex] = useState(-1);// 监听器所在下标，-1 为新增
  const [editingListenerFieldIndex, setEditingListenerFieldIndex] = useState(-1);// 字段所在下标，-1 为新增

  const [form] = Form.useForm(null);
  const [form1] = Form.useForm(null);
  const dataRef = useRef({});

  const saveId = `${prefix}:${componentType === "task" ? "TaskListener" : "ExecutionListener"}`;

  const resetListenersList = () => {
    dataRef.current.bpmnElement = window.bpmnInstances.bpmnElement;
    dataRef.current.otherExtensionList = [];
    dataRef.current.bpmnElementListeners =
      dataRef.current.bpmnElement.businessObject?.extensionElements?.values?.filter(ex => ex.$type === saveId) ?? [];
    const elementListenersList = dataRef.current.bpmnElementListeners.map(listener => initListenerType(listener));

    setElementListenersList(elementListenersList)
  }
  // 打开 监听器详情 侧边栏
  const openListenerForm = (listener, index) => {
    let listenerForm = {}
    if (listener) {
      listenerForm = initListenerForm(listener)
      setListenerForm(listenerForm)
      setEditingListenerIndex(index)
    } else {
      listenerForm = {}
      setListenerForm(listenerForm)
      setEditingListenerIndex(-1)// 标记为新增
    }
    if (listener && listener.fields) {
      const fieldsListOfListener = listener.fields.map(field => ({
        ...field,
        fieldType: field.string ? "string" : "expression"
      }));
      setFieldsListOfListener(fieldsListOfListener)
    } else {
      listenerForm = { ...listenerForm, "fields": [] }
      setFieldsListOfListener([])
      setListenerForm(listenerForm)
    }
    // 打开侧边栏并清楚验证状态
    setListenerFormModelVisible(true);

    setTimeout(() => form.resetFields(), 0);
  }
  // 移除监听器
  const removeListener = (index) => {
    dataRef.current.bpmnElementListeners.splice(index, 1);
    elementListenersList.splice(index, 1);
    setElementListenersList([...elementListenersList])
    updateElementExtensions(dataRef.current.bpmnElement, dataRef.current.otherExtensionList.concat(dataRef.current.bpmnElementListeners));
  }

  // 保存监听器配置
  const saveListenerConfig = async () => {
    let validateStatus = await form.validateFields();
    if (!validateStatus) return; // 验证不通过直接返回
    let newListenerForm = { ...listenerForm, ...validateStatus }

    const listenerObject = createListenerObject(newListenerForm, false, prefix);

    if (editingListenerIndex === -1) {
      dataRef.current.bpmnElementListeners.push(listenerObject);
      setElementListenersList([...elementListenersList, newListenerForm])
    } else {
      dataRef.current.bpmnElementListeners.splice(editingListenerIndex, 1, listenerObject);
      elementListenersList.splice(editingListenerIndex, 1, newListenerForm);
      setElementListenersList(elementListenersList)
    }
    // 保存其他配置
    dataRef.current.otherExtensionList = dataRef.current.bpmnElement.businessObject?.extensionElements?.values?.filter(ex => ex.$type !== saveId) ?? [];
    updateElementExtensions(dataRef.current.bpmnElement, dataRef.current.otherExtensionList.concat(dataRef.current.bpmnElementListeners));
    // 4. 隐藏侧边栏
    setListenerFormModelVisible(false)
    setListenerForm({});
  }

  // 打开监听器字段编辑弹窗
  const openListenerFieldForm = (field, index) => {
    const data = field ? JSON.parse(JSON.stringify(field)) : {}
    setListenerFieldForm(data);
    setEditingListenerFieldIndex(field ? index : -1);
    setListenerFieldFormModelVisible(true)
    setTimeout(() => form1.resetFields(), 0);
  }

  // 保存监听器注入字段
  const saveListenerFiled = async () => {
    let validateStatus = await form1.validateFields();
    if (!validateStatus) return; // 验证不通过直接返回
    if (editingListenerFieldIndex === -1) {
      setFieldsListOfListener([...fieldsListOfListener, validateStatus])
      setListenerForm({ ...listenerForm, "fields": [...listenerForm.fields, validateStatus] })
    } else {
      fieldsListOfListener.splice(editingListenerFieldIndex, 1, validateStatus);
      setFieldsListOfListener([...fieldsListOfListener])
      listenerForm.fields.splice(editingListenerFieldIndex, 1, validateStatus);
      setListenerForm({ ...listenerForm })
    }
    setListenerFieldFormModelVisible(false);
  }
  // 移除监听器字段
  const removeListenerField = (idx) => {
    fieldsListOfListener.splice(idx, 1);
    setFieldsListOfListener([...fieldsListOfListener])
    listenerForm.fields.splice(idx, 1);
    setListenerForm({ ...listenerForm })
  }

  useEffect(() => {
    id && id.length && resetListenersList();
  }, [id])

  return <div className={styles.listeners}>
    <Table
      size='small' bordered rowKey={"event"}
      className="bpmn_table"
      columns={columns(openListenerForm, removeListener, componentType)}
      pagination={false}
      dataSource={elementListenersList} />
    <Button onClick={() => openListenerForm(null)} type="primary" className={styles.add_btn} icon={<PlusOutlined />} >添加监听器</Button>

    <Drawer title="执行监听器" width={width} placement="right" visible={listenerFormModelVisible} onClose={() => setListenerFormModelVisible(false)}>
      <Form {..._layout} initialValues={listenerForm} form={form} name="listenerForm">
        <Form.Item
          name="event"
          label="事件类型"
          rules={[{ required: true, },]} >
          <Select placeholder="请选择" allowClear >
            {Object.keys(eventTypes).map(item => <Option value={item}>{eventTypes[item]}</Option>)}
          </Select>
        </Form.Item>
        {componentType === "task"
          ? <Form.Item
            name="id"
            label="监听器ID"
            rules={[{ required: true, },]} >
            <Input allowClear />
          </Form.Item>
          : null}
        <Form.Item
          name="listenerType"
          label="监听器类型"
          rules={[{ required: true, },]} >
          <Select placeholder="请选择" allowClear  >
            {Object.keys(listenerTypeObject).map(item => <Option value={item}>{listenerTypeObject[item]}</Option>)}
          </Select>
        </Form.Item>
        <Form.Item noStyle shouldUpdate={(prevValues, curValues) => prevValues.listenerType !== curValues.listenerType}>
          {({ getFieldValue }) => {
            const listenerType = getFieldValue('listenerType')
            switch (listenerType) {
              case 'classListener':

                return <Form.Item
                  name="class"
                  label="Java类"
                  rules={[{ required: true, },]} >
                  <Input allowClear />
                </Form.Item>

              case 'expressionListener':

                return <Form.Item
                  name="expression"
                  label="表达式"
                  rules={[{ required: true, },]} >
                  <Input allowClear />
                </Form.Item>

              case 'delegateExpressionListener':

                return <Form.Item
                  name="delegateExpression"
                  label="代理表达式"
                  rules={[{ required: true, },]} >
                  <Input allowClear />
                </Form.Item>

              case 'scriptListener':

                return <React.Fragment>
                  <Form.Item
                    name="scriptFormat"
                    label="脚本格式"
                    rules={[{ required: true, },]} >
                    <Input allowClear />
                  </Form.Item>
                  <Form.Item
                    name="scriptType"
                    label="脚本类型"
                    rules={[{ required: true, },]} >

                    <Select >
                      <Option value="inlineScript" >内联脚本</Option>
                      <Option value="externalScript" >外部脚本</Option>
                    </Select>
                  </Form.Item>

                  <Form.Item noStyle shouldUpdate={(prevValues, curValues) => prevValues.scriptType !== curValues.scriptType}>
                    {({ getFieldValue }) => {
                      const scriptType = getFieldValue('scriptType')

                      switch (scriptType) {
                        case 'inlineScript':
                          return <Form.Item
                            name="value"
                            label="脚本内容"
                            rules={[{ required: true, },]} >
                            <Input allowClear />
                          </Form.Item>

                        case 'externalScript':
                          return <Form.Item
                            name="resource"
                            label="资源地址"
                            rules={[{ required: true, },]} >
                            <Input allowClear />
                          </Form.Item>

                        default:
                          return null;
                      }
                    }}
                  </Form.Item>
                </React.Fragment>
              default:
                return null;
            }
          }}
        </Form.Item>
      </Form>
      <Divider style={{ margin: "0 0 16px" }} />
      <p style={{ display: " inline-flex", width: "100%", justifyContent: "space-between", alignItems: "center", marginTop: 0 }} >
        <span><AppstoreFilled style={{ position: "relative", top: -1, marginRight: "8px", fontSize: 12 }} />注入字段：</span>
        <Button size="mini" type="primary" onClick={() => openListenerFieldForm(null)}>添加字段</Button>
      </p>
      <Table
        size='small' bordered rowKey={"name"} className="bpmn_table" dataSource={fieldsListOfListener}
        columns={listenerFieldFormColumns(openListenerFieldForm, removeListenerField)} pagination={false}
      />
      <div style={{ display: "inline-flex", justifyContent: "space-around", marginTop: 8, width: "100%" }}>
        <Button style={btn_style} size="small" onClick={() => setListenerFormModelVisible(false)}>取 消</Button>
        <Button style={btn_style} size="small" type="primary" onClick={() => saveListenerConfig()}>保 存</Button>
      </div>
    </Drawer >

    <Gmodal
      title={'字段配置'} width={600}
      bodyStyle={{ height: 194, paddingBottom: 0 }}
      visible={listenerFieldFormModelVisible}
      handleOk={() => saveListenerFiled()}
      handleCancel={() => setListenerFieldFormModelVisible(false)} >
      <Form {...layout} initialValues={listenerFieldForm} preserve={false} form={form1} name="listenerFieldForm" >
        <Form.Item name="name" label="字段名称" rules={[{ required: true, },]}>
          <Input allowClear />
        </Form.Item>
        <Form.Item name="fieldType" label="字段类型" rules={[{ required: true, },]}>
          <Select placeholder="请选择" allowClear >
            {Object.keys(fieldTypeObject).map(item => <Option value={item}>{fieldTypeObject[item]}</Option>)}
          </Select>
        </Form.Item>
        <Form.Item noStyle shouldUpdate={(prevValues, currentValues) => prevValues.fieldType !== currentValues.fieldType} >
          {({ getFieldValue }) => {
            const fieldType = getFieldValue('fieldType');

            switch (fieldType) {

              case "string":
                form1.setFieldsValue({ expression: null })
                return <Form.Item name="string" label="字段值" rules={[{ required: true, },]}>
                  <Input allowClear />
                </Form.Item>

              case "expression":
                form1.setFieldsValue({ string: null })
                return <Form.Item name="expression" label="表达式" rules={[{ required: true, },]}>
                  <Input allowClear />
                </Form.Item>
              default:
                return null
            }
          }}
        </Form.Item>
      </Form>
    </Gmodal>
  </div >
};
export default Index;